﻿#include "lcd_hal.h"
#include "lcd_ext.h"
#include "os_obj.h"
#include "common.h"

/*****************************************************************************
* @brief   const 
*****************************************************************************/
#define PIX_LINE_MODE 0
#define PIX_WINDOW_MODE 1
#define PIX_POINT_MODE 0

#if PIX_LINE_MODE + PIX_WINDOW_MODE + PIX_POINT_MODE != 1
#error "pix mode sel error"
#endif

/*****************************************************************************
* @brief   extern var
*****************************************************************************/

/*****************************************************************************
* @brief   function
*****************************************************************************/

/*****************************************************************************
* @brief   loacal var
*****************************************************************************/
typedef struct
{
	// 字体信息
	uu16 font_x;
	uu16 font_y;

	uu16 font_color_set;	  //文字颜色设置
	uu16 font_back_color_set; //文字背景色设置
	uu16 font_color;		  //当前文字颜色
	uu16 font_back_color;	  //当前文字背景色

	uu16 font_cn_line_bytes;
	uu16 font_en_line_bytes;
	uu8 font_cn_tail_byte_mod;
	uu8 font_en_tail_byte_mod;

	// 中文和图片字符获取
	void *(*font_cn_get)(uu32 offset, uu32 bytes);
	void *(*img_num_get)(char ch, uu32 offset, uu32 size);

	// 英文字库内置
	const unsigned char *font_en_lib;

	uu16 ext_img_buff_size;	 // 外部数据缓存
	uu16 num_img_back_color; //记录数字图片背景色

	// 文字显示控制
	uu8 b_half_dot;
	uu8 font_space;
	uu8 b_anti_color;  //文字反色标志
	uu8 b_bk_color_en; //文字背景色使能
} lcd_cfg_type;

lcd_cfg_type lcd_cfg;

/******************************************************************************
	函数说明：在指定区域填充颜色
	入口数据：xsta,ysta   起始坐标
	xend,yend   终止坐标
	color  要填充的颜色
	返回值：  无
******************************************************************************/
void lcd_fill(u16 xsta, u16 ysta, u16 xend, u16 yend, u16 color)
{
	u16 i, j;
	lcd_window_set(xsta, ysta, xend - 1, yend - 1); //设置显示范围

	lcd_write_gram_begin();

	for (i = ysta; i < yend; i++)
	{
		for (j = xsta; j < xend; j++)
		{
			lcd_write_gram(color);
		}
	}

	lcd_write_gram_end();
}

/******************************************************************************
 函数说明：在指定位置画点
 入口数据：x,y 画点坐标
 color 点的颜色
 返回值：  无
******************************************************************************/
void lcd_draw_point(u16 x, u16 y, u16 color)
{
	lcd_cursor_set(x, y);	//设置光标位置
	lcd_write_gram_begin(); //开始写入GRAM
	lcd_write_gram(color);
	lcd_write_gram_end();
}

/******************************************************************************
 函数说明：画线
 入口数据：x1,y1   起始坐标
 x2,y2   终止坐标
 color   线的颜色
 返回值：  无
******************************************************************************/
void lcd_draw_line(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{
	u16 t;
	int xerr = 0, yerr = 0, delta_x, delta_y, distance;
	int incx, incy, uRow, uCol;
	
	lcd_window_set(0, 0, LCD_W - 1, LCD_H - 1); 
	
	delta_x = x2 - x1; //计算坐标增量
	delta_y = y2 - y1;
	uRow = x1; //画线起点坐标
	uCol = y1;
	if (delta_x > 0)
		incx = 1; //设置单步方向
	else if (delta_x == 0)
		incx = 0; //垂直线
	else
	{
		incx = -1;
		delta_x = -delta_x;
	}
	if (delta_y > 0)
		incy = 1;
	else if (delta_y == 0)
		incy = 0; //水平线
	else
	{
		incy = -1;
		delta_y = -delta_y;
	}
	if (delta_x > delta_y)
		distance = delta_x; //选取基本增量坐标轴
	else
		distance = delta_y;
	for (t = 0; t < distance + 1; t++)
	{
		lcd_draw_point(uRow, uCol, color); //画点
		xerr += delta_x;
		yerr += delta_y;
		if (xerr > distance)
		{
			xerr -= distance;
			uRow += incx;
		}
		if (yerr > distance)
		{
			yerr -= distance;
			uCol += incy;
		}
	}
}

/******************************************************************************
 函数说明：画矩形
 入口数据：x1,y1   起始坐标
 x2,y2   终止坐标
 color   矩形的颜色
 返回值：  无
******************************************************************************/
void lcd_draw_rectangle(u16 x1, u16 y1, u16 x2, u16 y2, u16 color)
{
	lcd_draw_line(x1, y1, x2, y1, color);
	lcd_draw_line(x1, y1, x1, y2, color);
	lcd_draw_line(x1, y2, x2, y2, color);
	lcd_draw_line(x2, y1, x2, y2, color);
}

/******************************************************************************
 函数说明：画圆
 入口数据：x0,y0   圆心坐标
 r  半径
 color   圆的颜色
 返回值：  无
******************************************************************************/
void lcd_draw_cricle(u16 x0, u16 y0, u8 r, u16 color)
{
	int a, b;
	
	lcd_window_set(0, 0, LCD_W - 1, LCD_H - 1); 
	
	a = 0;
	b = r;
	while (a <= b)
	{
		lcd_draw_point(x0 - b, y0 - a, color); //3
		lcd_draw_point(x0 + b, y0 - a, color); //0
		lcd_draw_point(x0 - a, y0 + b, color); //1
		lcd_draw_point(x0 - a, y0 - b, color); //2
		lcd_draw_point(x0 + b, y0 + a, color); //4
		lcd_draw_point(x0 + a, y0 - b, color); //5
		lcd_draw_point(x0 + a, y0 + b, color); //6
		lcd_draw_point(x0 - b, y0 + a, color); //7
		a++;
		if ((a * a + b * b) > (r * r)) //判断要画的点是否过远
		{
			b--;
		}
	}
}

/******************************************************************************
 函数说明：显示单个字符
 入口数据：x,y显示坐标
 num 要显示的字符
 sizey 字号
 mode:  0非叠加模式  1叠加模式
* 点阵模型
* byte0		 byte1
* b0 ... b7	 b0 ... b7
* b0 ... b7  b0 ... b7
* 返回值：  无
******************************************************************************/
void lcd_show_char(u16 x, u16 y, u8 num, u8 sizey, u8 mode)
{
	u8 temp, sizex, t, m = 0;
	u16 i, TypefaceNum; //一个字符所占字节大小
	u16 x0 = x;
	sizex = sizey / 2;
	TypefaceNum = (sizex / 8 + ((sizex % 8) ? 1 : 0)) * sizey;
	num = num - ' ';									//得到偏移后的值
	lcd_window_set(x, y, x + sizex - 1, y + sizey - 1); //设置光标位置

	lcd_write_gram_begin();

	for (i = 0; i < TypefaceNum; i++)
	{
		if (sizey == 12)
			temp = ascii_1206[num][i]; //调用6x12字体
		else if (sizey == 16)
			temp = ascii_1608[num][i]; //调用8x16字体
		else if (sizey == 24)
			temp = ascii_2412[num][i]; //调用12x24字体
		else if (sizey == 32)
			temp = ascii_3216[num][i]; //调用16x32字体
		else
			return;
		for (t = 0; t < 8; t++)
		{
			if (!mode) //非叠加模式
			{
				if (temp & (0x01 << t))
				{
					lcd_write_gram(lcd_cfg.font_color);
				}
				else
				{
					lcd_write_gram(lcd_cfg.font_back_color);
				}
				m++;
				if (m % sizex == 0)
				{
					m = 0;
					break;
				}
			}
			else //叠加模式
			{
				if (temp & (0x01 << t))
				{
					lcd_draw_point(x, y, lcd_cfg.font_color); //画一个点
				}
				x++;
				if ((x - x0) == sizex)
				{
					x = x0;
					y++;
					break;
				}
			}
		}
	}

	lcd_write_gram_end();
}

/******************************************************************************
函数说明：显示字符串
 入口数据：x,y显示坐标
 *p 要显示的字符串
 fc 字的颜色
 bc 字的背景色
 sizey 字号
 mode:  0非叠加模式  1叠加模式
 返回值：  无
******************************************************************************/
void lcd_show_string(u16 x, u16 y, const u8 *p, u8 sizey, u8 mode)
{
	while (*p != '\0')
	{
		// x 越界退出
		if (x + (sizey >> 1) > LCD_W)
			break;

		// 显示字符
		lcd_show_char(x, y, *p, sizey, mode);
		x += sizey >> 1;
		p++;
	}
}

/******************************************************************************
 函数说明：显示图片
 入口数据：x,y起点坐标
 length 图片长度
 width  图片宽度
 pic[]  图片数组
 返回值：  无
******************************************************************************/
void lcd_show_picture(u16 x, u16 y, u16 length, u16 width, const u8 pic[])
{
	u16 dat;
	u16 *pdat;
	u16 i, j;

	lcd_window_set(x, y, x + length - 1, y + width - 1);

	pdat = (u16 *)pic;

	lcd_write_gram_begin();

	for (i = 0; i < length; i++)
	{
		for (j = 0; j < width; j++)
		{
			dat = *pdat++;
			lcd_write_gram(dat);
		}
	}

	lcd_write_gram_end();
}

void lcd_put_img_nums(uu16 x0, uu16 y0, char *ns)
{
	char index;
	char ch;
	u16 wide, hight;

	ch = *ns++;
	while (ch)
	{
		index = -1;

		if (ch == '-')
		{
			index = 10;
		}
		else if (ch == '.')
		{
			index = 11;
		}
		else if (ch == ':')
		{
			index = 12;
		}
		else if (ch == ' ')
		{
			index = 0x20;
		}
		else if ((ch >= '0') && (ch <= '9'))
		{
			index = ch - '0';
		}
		else
		{
			break;
		}

		if (0x20 != index)
		{
			uu32 rd_offset = 0;
			uu16 rd_line, rd_bytes, y_offset;

			uu16 *buff = lcd_cfg.img_num_get(index, 0, 6);

			// 图片信息
			wide = buff[0];
			hight = buff[1];

			// 图片信息检查
			if ((x0 + wide > LCD_W) || (y0 + hight > LCD_H))
			{
				break;
			}

			if ((wide > LCD_W) || (hight > LCD_H))
			{
				break;
			}

			if ((hight == 0) || (wide == 0))
			{
				break;
			}

			lcd_cfg.num_img_back_color = buff[2];

			// 读取配置
			rd_line = (lcd_cfg.ext_img_buff_size >> 1) / buff[0]; // 每次读取行数
			y_offset = 0;										  // 行位置
			rd_offset = 4;

			// 输出
			while (y_offset < hight)
			{
				// 读取尾行检测
				if (y_offset + rd_line > hight)
				{
					rd_line = hight - y_offset;
				}
				rd_bytes = rd_line * wide * 2; // 每次读取字节数
				buff = lcd_cfg.img_num_get(index, rd_offset, rd_bytes);
				// 显示
				lcd_show_picture(x0, y0 + y_offset, wide, rd_line, (void *)buff);

				// 增量
				y_offset += rd_line;
				rd_offset += rd_bytes;
			}
			x0 += wide;
		}
		else
		{
			lcd_fill(x0, y0, x0 + wide, y0 + hight, lcd_cfg.num_img_back_color);
			x0 += wide;
		}
		ch = *ns++;
	}
}

void lcd_insert_space(u16 x, u16 y, u16 wide)
{
	u16 dat;
	u16 i, j;

	if (wide <= 0)
		return;

	if (!lcd_cfg.b_bk_color_en)
		return;

	lcd_window_set(x, y, x + wide - 1, y + lcd_cfg.font_y - 1);

	lcd_write_gram_begin();

	for (i = 0; i < wide; i++)
	{
		for (j = 0; j < lcd_cfg.font_y; j++)
		{
			dat = lcd_cfg.font_back_color;
			lcd_write_gram(dat);
		}
	}

	lcd_write_gram_end();
}

/******************************************************************************
* gb2312 display for ts3
******************************************************************************/
static uu16 lcd_gb2312_get(uu16 wch)
{
	UINT16_VAL ch;

	ch.uVal = wch;

	if (ch.byte.LB < 0xa1)
		return 0;
	if (ch.byte.LB > 0xfe)
		return 0;
	if (ch.byte.HB < 0xa1)
		return 0;
	if (ch.byte.HB > 0xfe)
		return 0;

	ch.byte.HB -= 0xa1;
	ch.byte.LB -= 0xa1;

	return (94UL * ch.byte.HB + ch.byte.LB);
}

/******************************************************************************
* gb2312 display for ts3
* 点阵模型
* byte0			 byte1
* b7 b6 ... b0	 b7 b6 ... b0
* b7 b6 ... b0   b7 b6 ... b0
******************************************************************************/
void lcd_show_cn(u16 x, u16 y, const unsigned char *pdat)
{
	u16 i, j, lcnt;
	u16 fdat, bdat;
	u16 line_bytes, line_tail_bits;

	fdat = lcd_cfg.font_color;
	bdat = lcd_cfg.font_back_color;
	
	// 计算 行列尺寸
	line_bytes = lcd_cfg.font_cn_line_bytes;
	line_tail_bits = lcd_cfg.font_cn_tail_byte_mod;

#if PIX_WINDOW_MODE > 0
	lcd_window_set(x, y, x + lcd_cfg.font_x - 1, y + lcd_cfg.font_y - 1);
	lcd_write_gram_begin();
#endif

	// 点输出
	if (lcd_cfg.b_bk_color_en)
	{
		// 背景色模式
		for (lcnt = 0; lcnt < lcd_cfg.font_y; lcnt++)
		{
#if PIX_LINE_MODE > 0
			lcd_cursor_set(x, y + lcnt);
			lcd_write_gram_begin();
#endif
			for (i = 0; i < line_bytes; i++)
			{
				uu8 ds;
				uu8 en_bits;

				ds = *pdat++;

				if (!line_tail_bits)
				{
					en_bits = 8;
				}
				else
				{
					if (i != (line_bytes - 1))
						en_bits = 8;
					else
						en_bits = line_tail_bits;
				}

				for (j = 0; j < en_bits; j++)
				{
					if (ds & 0x80)
					{
						lcd_write_gram(fdat);
					}
					else
					{
						lcd_write_gram(bdat);
					}

					ds <<= 1;
				}
			}
#if PIX_LINE_MODE > 0
			lcd_write_gram_end();
#endif
		}
	}
	else
	{
		// 无背景色
		for (lcnt = 0; lcnt < lcd_cfg.font_y; lcnt++)
		{
			for (i = 0; i < line_bytes; i++)
			{
				uu8 ds;
				uu8 en_bits;

				ds = *pdat++;

				if (!line_tail_bits)
				{
					en_bits = 8;
				}
				else
				{
					if (i != (line_bytes - 1))
						en_bits = 8;
					else
						en_bits = line_tail_bits;
				}

				for (j = 0; j < en_bits; j++)
				{
					if (ds & 0x80)
					{
						lcd_draw_point(x + i * 8 + j, y + lcnt, fdat);
					}

					ds <<= 1;
				}
			}
		}
	}

#if PIX_WINDOW_MODE > 0
	lcd_write_gram_end();
#endif
}

void lcd_show_gbk(u16 x, u16 y, uu16 ch)
{
	u16 line_bytes;

	const unsigned char *pdat;

	if (lcd_cfg.font_cn_get == 0)
		return;

	line_bytes = lcd_cfg.font_cn_line_bytes;

	pdat = lcd_cfg.font_cn_get(lcd_gb2312_get(ch) * lcd_cfg.font_y * line_bytes, lcd_cfg.font_y * line_bytes);

	lcd_show_cn(x, y, pdat);
}

/******************************************************************************
* ascii display for PctoLCD
* 点阵模型
* byte0		 byte1
* b0 ... b7	 b0 ... b7
* b0 ... b7  b0 ... b7
******************************************************************************/
void lcd_show_ascii(u16 x, u16 y, uu16 ch)
{
	u16 lcnt, i, j;
	u16 line_bytes, line_tail_bits;
	const unsigned char *pdat;
	u16 fdat, bdat;

	line_bytes = lcd_cfg.font_en_line_bytes;
	line_tail_bits = lcd_cfg.font_en_tail_byte_mod;

	pdat = &lcd_cfg.font_en_lib[(ch - 0x20) * lcd_cfg.font_y * line_bytes];

	fdat = lcd_cfg.font_color;
	bdat = lcd_cfg.font_back_color;

	// 窗口
#if PIX_WINDOW_MODE > 0
	lcd_window_set(x, y, x + (lcd_cfg.font_x >> 1) - 1, y + lcd_cfg.font_y - 1);
	lcd_write_gram_begin();
#endif

	// 点输出
	if (lcd_cfg.b_bk_color_en)
	{
		// 背景色模式
		for (lcnt = 0; lcnt < lcd_cfg.font_y; lcnt++)
		{

#if PIX_LINE_MODE > 0
			lcd_cursor_set(x, y + lcnt);
			lcd_write_gram_begin();
#endif
			for (i = 0; i < line_bytes; i++)
			{
				uu8 ds;
				uu8 en_bits;
				ds = *pdat++;

				if (!line_tail_bits)
				{
					en_bits = 8;
				}
				else
				{
					if (i != (line_bytes - 1))
					{
						en_bits = 8;
					}
					else
					{
						en_bits = line_tail_bits;
					}
				}

				for (j = 0; j < en_bits; j++)
				{
					if (ds & 0x01)
					{
						lcd_write_gram(fdat);
					}
					else
					{
						lcd_write_gram(bdat);
					}

					ds >>= 1;
				}
			}

#if PIX_LINE_MODE > 0
			lcd_write_gram_end();
#endif
		}
	}
	else
	{
		for (lcnt = 0; lcnt < lcd_cfg.font_y; lcnt++)
		{
			// 无背景色
			for (i = 0; i < line_bytes; i++)
			{
				uu8 ds;
				uu8 en_bits;

				ds = *pdat++;

				if (!line_tail_bits)
				{
					en_bits = 8;
				}
				else
				{
					if (i != (line_bytes - 1))
						en_bits = 8;
					else
						en_bits = line_tail_bits;
				}

				for (j = 0; j < en_bits; j++)
				{
					if (ds & 0x80)
					{
						lcd_draw_point(x + i * 8 + j, y + lcnt, lcd_cfg.font_color);
					}

					ds <<= 1;
				}
			}
		}
	}

#if PIX_WINDOW_MODE > 0
	lcd_write_gram_end();
#endif
}

/*****************************************************************************
* @brief   puts string
*****************************************************************************/
void lcd_puts(uu16 x0, uu16 y0, const uu8 *chs)
{
	word_tt dat;
	uu16 half_x;

	half_x = lcd_cfg.font_x >> 1;

	while (*chs)
	{
		if (*chs < 0x80)
		{
			if (x0 + half_x > LCD_W)
			{
				break;
			}

			lcd_show_ascii(x0, y0, *chs);

			if (!lcd_cfg.b_half_dot || (*chs != '.'))
				x0 += half_x;
			else
				x0 += (half_x + 1) >> 1;

			lcd_insert_space(x0, y0, lcd_cfg.font_space);
			x0 += lcd_cfg.font_space;

			chs++;
		}
		else
		{
			if (!chs[1])
			{
				break;
			}

			if (x0 + lcd_cfg.font_x > LCD_W)
			{
				break;
			}

			dat.byte.HB.uval = *chs++;
			dat.byte.LB.uval = *chs++;
			lcd_show_gbk(x0, y0, dat.uval);

			x0 += lcd_cfg.font_x;

			lcd_insert_space(x0, y0, lcd_cfg.font_space);
			x0 += lcd_cfg.font_space;
		}
	}
}

/*****************************************************************************
* @brief   img display
*****************************************************************************/
void lcd_show_format_pic(uu16 x0, uu16 y0, const u16 *img)
{
	if (x0 + img[0] <= LCD_W && y0 + img[1] <= LCD_H)
	{
		lcd_show_picture(x0, y0, img[0], img[1], (uu8 *)&img[2]);
	}
}

/*****************************************************************************
* @brief   img cut display
*****************************************************************************/
void lcd_show_cut_pic(
	uu16 x0, uu16 y0,
	uu16 cut_x0, uu16 cut_y0,
	uu16 cut_wide, uu16 cut_hight,
	const u16 *img)
{
	uu16 img_x, img_y;
	uu16 y_now;

	img_x = img[0];
	img_y = img[1];

	// 参数限定
	if (x0 + cut_wide > LCD_W)
		cut_wide = LCD_W - x0;

	if (y0 + cut_hight > LCD_H)
		cut_hight = LCD_H - y0;

	if (cut_x0 + cut_wide > img_x)
		cut_wide = img_x - cut_x0;

	if (cut_y0 + cut_hight > img_y)
		cut_hight = img_y - cut_y0;

	if ((cut_wide > LCD_W) || (cut_hight > LCD_H))
	{
		return;
	}

	// 截取显示
	for (y_now = 0; y_now < cut_hight; y_now++)
	{
		lcd_show_picture(x0, y0 + y_now, cut_wide, 1, (uu8 *)&img[2 + (cut_y0 + y_now) * img_x + cut_x0]);
	}
}

/*****************************************************************************
* @brief   外部存储区图片
*****************************************************************************/
void lcd_show_ext_pic(uu16 x0, uu16 y0, void *(*img_get)(uu32 f_offset, uu32 rd_len))
{
	uu32 rd_offset = 0;
	uu16 rd_line, rd_bytes, y_offset, wide, hight;

	uu16 *buff = img_get(0, 4);

	// 图片信息
	wide = buff[0];
	hight = buff[1];

	// 参数检查
	if ((x0 + wide > LCD_W) || (y0 + hight > LCD_H))
	{
		return;
	}

	if ((wide > LCD_W) || (hight > LCD_H))
	{
		return;
	}

	if ((hight == 0) || (wide == 0))
	{
		return;
	}

	// 读取配置
	rd_line = (lcd_cfg.ext_img_buff_size >> 1) / buff[0]; // 每次读取行数
	y_offset = 0;										  // 行位置
	rd_offset = 4;

	// 合法检测
	if (rd_line == 0)
		return;

	// 输出
	while (y_offset < hight)
	{
		// 读取尾行检测
		if (y_offset + rd_line >= hight)
		{
			rd_line = hight - y_offset;
		}
		rd_bytes = rd_line * wide * 2; // 每次读取字节数
		buff = img_get(rd_offset, rd_bytes);
		// 显示
		lcd_show_picture(x0, y0 + y_offset, wide, rd_line, (void *)buff);

		// 增量
		y_offset += rd_line;
		rd_offset += rd_bytes;
	}
}

/*****************************************************************************
* @brief   img cut display
*****************************************************************************/
void lcd_show_cut_ext_pic(
	uu16 x0, uu16 y0,
	uu16 cut_x0, uu16 cut_y0,
	uu16 cut_wide, uu16 cut_hight,
	void *(*img_get)(uu32 f_offset, uu32 rd_len))
{
	uu16 img_x, img_y;
	uu16 y_now;

	uu16 *buff = img_get(0, 6);

	// 图片行尺寸
	img_x = buff[0];
	img_y = buff[1];

	if ((img_y > 4096) || (img_x > 4096))
	{
		return;
	}

	if ((img_y == 0) || (img_x == 0))
	{
		return;
	}

	// 参数限定
	if (x0 + cut_wide > LCD_W)
		cut_wide = LCD_W - x0;

	if (y0 + cut_hight > LCD_H)
		cut_hight = LCD_H - y0;

	if (cut_x0 + cut_wide > img_x)
		cut_wide = img_x - cut_x0;

	if (cut_y0 + cut_hight > img_y)
		cut_hight = img_y - cut_y0;

	if ((cut_wide > LCD_W) || (cut_hight > LCD_H))
	{
		return;
	}

	// 截取显示
	for (y_now = 0; y_now < cut_hight; y_now++)
	{
		uu32 offset;

		// 数据地址偏移量
		offset = (cut_y0 + y_now) * img_x + cut_x0 + 2;
		offset <<= 1;
		// 读取图片
		buff = img_get(0, cut_wide << 1);
		// 显示
		lcd_show_picture(x0, y0 + y_now, cut_wide, 1, (void *)buff);
	}
}

/*****************************************************************************
* @brief   extern par config
*****************************************************************************/
void lcd_font_space_set(char space)
{
	lcd_cfg.font_space = space;
}

void lcd_half_dot_en(void)
{
	lcd_cfg.b_half_dot = 1;
}

void lcd_half_dot_dis(void)
{
	lcd_cfg.b_half_dot = 0;
}

void lcd_font_en_set(const unsigned char *en)
{
	lcd_cfg.font_en_lib = en;
}

void lcd_font_cn_set(void *(*font_cn_get)(uu32, uu32))
{
	lcd_cfg.font_cn_get = font_cn_get;
}

void lcd_img_font_set(void *(*img_num_get)(char, uu32, uu32))
{
	lcd_cfg.img_num_get = img_num_get;
}

void lcd_font_size_set(uu16 x, uu16 y)
{
	uu16 line_c_bytes;

	lcd_cfg.font_x = x;
	lcd_cfg.font_y = y;

	// EN 字符信息
	line_c_bytes = (lcd_cfg.font_x >> 1) >> 3;
	lcd_cfg.font_en_tail_byte_mod = (lcd_cfg.font_x >> 1) & 0x07;
	if (lcd_cfg.font_en_tail_byte_mod)
		lcd_cfg.font_en_line_bytes = line_c_bytes + 1;
	else
		lcd_cfg.font_en_line_bytes = line_c_bytes;

	// CN 字符信息
	line_c_bytes = lcd_cfg.font_x >> 3;
	lcd_cfg.font_cn_tail_byte_mod = lcd_cfg.font_x & 0x07;
	if (lcd_cfg.font_cn_tail_byte_mod)
		lcd_cfg.font_cn_line_bytes = line_c_bytes + 1;
	else
		lcd_cfg.font_cn_line_bytes = line_c_bytes;
}

void lcd_font_color_set(uu16 f_color, uu16 b_color)
{
	lcd_cfg.font_color_set = f_color;
	lcd_cfg.font_back_color_set = b_color;

	if (lcd_cfg.b_anti_color)
	{
		lcd_cfg.font_color = lcd_cfg.font_back_color_set;
		lcd_cfg.font_back_color = lcd_cfg.font_color_set;
	}
	else
	{
		lcd_cfg.font_color = lcd_cfg.font_color_set;
		lcd_cfg.font_back_color = lcd_cfg.font_back_color_set;
	}
}

void lcd_anti_color_en(void)
{
	lcd_cfg.b_anti_color = 1;

	lcd_cfg.font_color = lcd_cfg.font_back_color_set;
	lcd_cfg.font_back_color = lcd_cfg.font_color_set;
}

void lcd_anti_color_dis(void)
{
	lcd_cfg.b_anti_color = 0;

	lcd_cfg.font_color = lcd_cfg.font_color_set;
	lcd_cfg.font_back_color = lcd_cfg.font_back_color_set;
}

void lcd_ext_buff_size(uu16 size)
{
	lcd_cfg.ext_img_buff_size = size;
}

void lcd_font_bk_color_en(uu8 st)
{
	lcd_cfg.b_bk_color_en = st;
}

void lcd_init(void)
{
	lcd_hal_init();
	lcd_font_en_set(ascii_2412[0]);
	lcd_font_size_set(24, 24);
	lcd_font_color_set(COLOR_GEN(LIGHTBLUE), COLOR_GEN(DARKBLUE));
	lcd_font_space_set(0);
	lcd_half_dot_dis();
	lcd_font_bk_color_en(1);
	
}